package com.coincalf.wallet.task.collect;//package com.yrj.task.collecttask;

import com.coincalf.framework.enums.TxStateEnum;
import com.coincalf.wallet.blockchain.client.UsdtClientSingleton;
import com.coincalf.wallet.blockchain.client.Web3jSingleton;
import com.coincalf.wallet.entity.CoinRecharge;
import com.coincalf.wallet.entity.CollectCoinRecord;
import com.coincalf.wallet.service.CoinRechargeService;
import com.coincalf.wallet.service.CollectCoinRecordService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import wf.bitcoin.javabitcoindrpcclient.BitcoindRpcClient;
import wf.bitcoin.javabitcoindrpcclient.GenericRpcException;

import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * 更新归集纪录的交易状态
 */
@Component
@EnableScheduling
public class SyncCollectRecordsStatus {

    private static final Logger log = LoggerFactory.getLogger(SyncCollectRecordsStatus.class);

    @Autowired
    private CoinRechargeService coinRechargeService;
    @Autowired
    private CollectCoinRecordService collectCoinRecordService;


    /**
     * 同步ETH归集交易
     */
    @Scheduled(cron = "*/50 * * * * ?")
    public void syncEthDepositTx() {
        log.info("开始执行更新ETH归集交易状态任务");
        syncEthTask("ETH");
    }

    /**
     * 同步USDT_ERC20归集交易
     */
    @Scheduled(cron = "*/40 * * * * ?")
    public void syncUSDTErc20DepositTx() {
        log.info("开始执行更新USDT_ERC20归集交易状态任务");
        syncEthTask("USDT_ERC20");
    }

    /**
     * ETH系列交易确认查询
     *
     * @param coinName
     */
    public void syncEthTask(String coinName) {
        List<CollectCoinRecord> collectionRecords = collectCoinRecordService.findAllByCoinNameAndTxStatus(coinName, TxStateEnum.TO_BE_CONFIRMED.getStatus());
        long newestBlock;
        try {
            newestBlock = Web3jSingleton.getWeb3j().ethBlockNumber().send().getBlockNumber().longValue();
        } catch (Exception e) {
            log.error("RPC查询当前最新高度失败 e={}", e);
            return;
        }
        for (CollectCoinRecord c : collectionRecords) {
            Optional<TransactionReceipt> transactionReceipt;
            try {
                transactionReceipt = Web3jSingleton.getAdmin().ethGetTransactionReceipt(c.getTxId()).send().getTransactionReceipt();
            } catch (Exception e) {
                log.error("RPC查询{}交易失败 txId={}  e={}", coinName, c.getTxId(), e);
                continue;
            }

            Boolean success = transactionReceipt.map(TransactionReceipt::getStatus).map("0x1"::equals).orElse(null);
            if (success != null) {
                if (success) {
                    //交易成功
                    //区块确认数
                    long confirmations = newestBlock - transactionReceipt.get().getBlockNumber().longValue() + 1;
                    if (confirmations > 3) {
                        c.setTxStatus(TxStateEnum.SUCCESS.getStatus());
                        c.setLastUpdateTime(new Date());
                        collectCoinRecordService.updateById(c);
                    }
                } else {
                    //交易失败
                    c.setTxStatus(TxStateEnum.FAIL.getStatus());
                    c.setLastUpdateTime(new Date());
                    collectCoinRecordService.updateById(c);
                    log.info("{}归集交易失败，txId={}", coinName, c.getTxId());
                    //同时交易修改为未归集
                    String chainOrderId = c.getCoinRechargeId();
                    String[] split = chainOrderId.split(",");
                    for (String s : split) {
                        if (StringUtils.isNotBlank(s)) {
                            CoinRecharge coinRecharge = coinRechargeService.selectById(Long.valueOf(s));
                            coinRecharge.setCollected(0);
                            coinRecharge.setLastUpdateTime(new Date());
                            coinRechargeService.updateById(coinRecharge);
                            log.info("{}归集交易失败 修改充币交易未未归集成功 充币主键id={} txId={}", coinName, s, c.getTxId());
                        }
                    }
                }
            } else {
                log.warn("{}归集交易待确认... txId={}", c.getCoinId(), c.getTxId());
            }
        }
    }

    @Scheduled(cron = "* */15 * * * ?")
    public void syncBtcCollectTx() {
        syncBtcTask("BTC");
    }

    @Scheduled(cron = "0 0/15 * * * ?")
    public void syncUSDTOmniCollectTx() {
        syncBtcTask("USDT_OMNI");
    }

    /**
     * BTC系列交易确认查询
     */
    public void syncBtcTask(String coinName) {
        List<CollectCoinRecord> collectCoinRecords = collectCoinRecordService.findAllByCoinNameAndTxStatus(coinName, TxStateEnum.TO_BE_CONFIRMED.getStatus());

        for (CollectCoinRecord c : collectCoinRecords) {
            //查询交易详情
            BitcoindRpcClient.RawTransaction tx;
            try {
                tx = UsdtClientSingleton.getUsdtClient().getRawTransaction(c.getTxId());
            } catch (GenericRpcException e) {
                continue;
            }
            //确认数
            int confirmations = tx.confirmations();
            if (confirmations > 2) {
                //区块确认数大于2 则进行确认 否则不做处理
                //交易确认数量大于2 直接设置成功 增加用户余额
                c.setTxStatus(TxStateEnum.SUCCESS.getStatus());
                c.setLastUpdateTime(new Date());
                collectCoinRecordService.updateById(c);
            }
        }
    }

}


